jQuery.validator.addMethod("idCardValid", function(value, element) {
    return this.optional(element) || eighteenPlaceIdCardValidation(value);
}, "请输入有效的身份证号码！");

jQuery.validator.addMethod("mobileValid", function(value, element) {
    return this.optional(element) || mobileValidation(value);
}, "请输入有效的手机号码！");

jQuery.validator.addMethod("emailValid", function(value, element) {
    return this.optional(element) || emailValidation(value);
}, "请输入有效的邮箱！");

jQuery.validator.addMethod("unifiedSocialCreditCodeValid", function (value, element) {
    return this.optional(element) || unifiedSocialCreditCodeValid(value);
}, "请输入有效的统一信用代码！");

jQuery.validator.addMethod("bankCardValid", function (value, element) {
    return this.optional(element) || bankCardValid(value);
}, "请输入有效的银行卡号！");

jQuery.validator.addMethod("notEqualTo", function(value, element ,param) {
    var target = $(param);
    return value !== target.val();
}, "两个值必须不一致！");

/**
 * obj是否不等于null
 * @param {Object} obj
 */
function isNotNull(obj) {
    return obj !== null && obj !== undefined;
}

/**
 * obj是否不等于null或""
 * @param {Object} obj
 */
function isNotNullOrEmptyString(obj) {
    return isNotNull(obj) && obj.replace(/(^s*)|(s*$)/g, "").length != 0;
}

/**
 * 十八位身份证号码校验
 * @param {Object} idCard
 */
function eighteenPlaceIdCardValidation(idCard) {
    if(!(isNotNullOrEmptyString(idCard)) || !(new RegExp("^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$").test(idCard))) {
        return false;
    }
    var checkCode = new Array("1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2");
    var sum = 0;
    for(var i = 17, j = 0; i > 0; i--, j++) {
        sum += parseInt(Math.pow(2, i)) * parseInt(idCard[j]);
    }
    var remainder = sum % 11;
    return(remainder >= 0 && remainder <= 10) && idCard.substring((idCard.length - 1), idCard.length).toUpperCase() === checkCode[remainder];
}

/**
 * 手机号码校验
 * @param {Object} mobile
 */
function mobileValidation(mobile) {
    // 移动号段: 134 135 136 137 138 139 147 150 151 152 157 158 159 178 182 183 184 187 188 148 172 198
    // 联通号段: 130 131 132 155 156 185 186 145 176 146 166 171 175
    // 电信号段: 133 153 173 177 180 181 189 174 149 199
    // 虚拟运营商号段: 170
    return isNotNullOrEmptyString(mobile) && new RegExp("^((13[0-9])|(14[5-9])|(15([0-3]|[5-9]))|(17[0-8])|(18[0-9])|(19[8-9]))\\d{8}$").test(mobile);
}

/**
 * 邮箱校验
 * @param {Object} email
 */
function emailValidation(email) {
    return isNotNullOrEmptyString(email) && new RegExp("^[A-Za-z\\d]+([-_.][A-Za-z\\d]+)*@([A-Za-z\\d]+[-.])+[A-Za-z\\d]{2,4}$").test(email);
}

/**
 * 十八位统一社会代码校验
 * @param {Object} code
 */
function unifiedSocialCreditCodeValid(code) {
    if (isNotNullOrEmptyString(code) && new RegExp("^((1{1}[1-39]{1})|(5{1}[1-39]{1})|(9{1}[1-3]{1})|(Y1))[0-9]{6}[0-9A-HJ-NP-RT-UW-Y]{10}$").test(code)) {
        var letter = "0123456789ABCDEFGHJKLMNPQRTUWXY";
        var divisor = new Array(1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28);
        var sum = 0;
        var codeLen = code.length;
        for (var i = 0; i < codeLen - 1; i++) {
            if (code[i] >= 'A' && code[i] <= 'Z') {
                sum += letter.indexOf(code[i]) * divisor[i];
            } else {
                sum += parseInt(code[i]) * divisor[i];
            }
        }
        var letterLen = letter.length;
        var remainder = letterLen - (sum % letterLen);
        if (remainder >= letterLen)
            return false;
        return letter[remainder] == code.substring(codeLen - 1, codeLen);
    }
    return false;
}

/**
 * 16位或19位银行卡号（借记卡、信用卡）校验
 * @param {Object} bankCardNumber
 */
function bankCardValid(bankCardNumber) {
    if (isNotNullOrEmptyString(bankCardNumber) && new RegExp("^([0-9]{16}|[0-9]{19})$").test(bankCardNumber)) {
        var bankCardNumberLen = bankCardNumber.length;
        var arr = new Array();
        for (var i = 0; i < bankCardNumberLen; i++) {
            arr[i] = parseInt(bankCardNumber[i]);
        }
        console.log(arr);
        for (var i = bankCardNumberLen - 2; i >= 0; i -= 2) {
            arr[i] = arr[i] * 2;
            arr[i] = parseInt(arr[i] / 10) + arr[i] % 10;
        }
        console.log(arr);
        var sum = 0;
        for (var i = 0; i < bankCardNumberLen; i++) {
            sum += arr[i];
        }
        return sum % 10 == 0;
    }
    return false;
}